package io.gitee.kotle.player.ui.view.exo;

import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.CornerPathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import io.gitee.kotle.player.R;
import kotlin.Unit;
import kotlin.jvm.functions.Function0;

public class PlayPauseView extends View {

    public static int STATE_PLAY = 0;

    public static int STATE_PAUSE = 1;

    public static int DEFAULT_LINE_COLOR = Color.WHITE;

    public static int DEFAULT_BG_LINE_COLOR = 0xfffafafa;

    public static int DEFAULT_LINE_WIDTH = 4;

    public static int DEFAULT_BG_LINE_WIDTH = 4;

    public static int DEFAULT_DURATION = 1200;

    private int mCurrentState = STATE_PAUSE;

    private final Paint mPaint, mBgPaint;

    private int mWidth, mHeight;

    private int mCenterX, mCenterY;

    private int mCircleRadius;

    private RectF mRectF, mBgRectF;

    private float mFraction = 1;

    private final Path mPath, mDstPath;

    private final PathMeasure mPathMeasure;

    private float mPathLength;

    private int mDuration;

    public PlayPauseView(Context context) {
        this(context, null);
    }

    public PlayPauseView(Context context, AttributeSet attrs) {
        super(context, attrs);
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.PlayPauseView);
        int lineColor = ta.getColor(R.styleable.PlayPauseView_playLineColor, DEFAULT_LINE_COLOR);
        int bgLineColor = ta.getColor(R.styleable.PlayPauseView_playBgLineColor, DEFAULT_BG_LINE_COLOR);
        int lineWidth = ta.getDimensionPixelSize(R.styleable.PlayPauseView_playLineWidth, DEFAULT_LINE_WIDTH);
        mCircleRadius = ta.getDimensionPixelSize(R.styleable.PlayPauseView_playLineCircleRadius, mCircleRadius);
        int bgLineWidth = ta.getDimensionPixelSize(R.styleable.PlayPauseView_playBgLineWidth, DEFAULT_BG_LINE_WIDTH);
        ta.recycle();

        setLayerType(View.LAYER_TYPE_SOFTWARE, null);

        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        mPaint.setColor(lineColor);
        mPaint.setStrokeWidth(lineWidth);
        mPaint.setPathEffect(new CornerPathEffect(1));

        mBgPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mBgPaint.setStyle(Paint.Style.STROKE);
        mBgPaint.setStrokeCap(Paint.Cap.ROUND);
        mBgPaint.setColor(bgLineColor);
        mBgPaint.setStrokeWidth(bgLineWidth);

        mPath = new Path();
        mDstPath = new Path();
        mPathMeasure = new PathMeasure();

        mDuration = DEFAULT_DURATION;
    }

    public void setLineColor(int color) {
        mPaint.setColor(color);
    }

    public void setLineWidth(float width) {
        mPaint.setStrokeWidth(width);
    }

    public void setBgLineColor(int color) {
        mBgPaint.setColor(color);
    }

    public void setBgLineWidth(float width) {
        mBgPaint.setStrokeWidth(width);
    }

    @Override
    protected void onSizeChanged(int newW, int newH, int oldw, int oldh) {
        super.onSizeChanged(newW, newH, oldw, oldh);
        int w = (newW - getPaddingStart() - getPaddingEnd());
        int h = (newH - getPaddingTop() - getPaddingBottom());
        mWidth = (int) (w - mBgPaint.getStrokeWidth() * 2);
        mHeight = (int) (h - mBgPaint.getStrokeWidth() * 2);
        if (mCircleRadius <= 0) {
            mCircleRadius = mWidth / dp2px(3);
        }
        mCenterX = w / 2 + getPaddingStart();
        mCenterY = h / 2 + getPaddingTop();
        mRectF = new RectF(mCenterX - mCircleRadius, mCenterY + 0.6f * mCircleRadius,
                mCenterX + mCircleRadius, mCenterY + 2.6f * mCircleRadius);
        mBgRectF = new RectF(mCenterX - mWidth / 2f, mCenterY - mHeight / 2f, mCenterX + mWidth / 2f, mCenterY + mHeight / 2f);
        mPath.moveTo(mCenterX - mCircleRadius, mCenterY + 1.8f * mCircleRadius);
        mPath.lineTo(mCenterX - mCircleRadius, mCenterY - 1.8f * mCircleRadius);
        mPath.lineTo(mCenterX + mCircleRadius, mCenterY);
        mPath.close();
        mPathMeasure.setPath(mPath, false);
        mPathLength = mPathMeasure.getLength();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawCircle(mCenterX, mCenterY, mWidth / 2f, mBgPaint);
        if (mFraction < 0) {    //嗷~~ 弹性部分
            canvas.drawLine(mCenterX + mCircleRadius, mCenterY - 1.6f * mCircleRadius + 10 * mCircleRadius * mFraction,
                    mCenterX + mCircleRadius, mCenterY + 1.6f * mCircleRadius + 10 * mCircleRadius * mFraction, mPaint);

            canvas.drawLine(mCenterX - mCircleRadius, mCenterY - 1.6f * mCircleRadius,
                    mCenterX - mCircleRadius, mCenterY + 1.6f * mCircleRadius, mPaint);

            canvas.drawArc(mBgRectF, -105, 360, false, mPaint);
        } else if (mFraction <= 0.3) {  //嗷~~ 右侧直线和下方曲线
            canvas.drawLine(mCenterX + mCircleRadius, mCenterY - 1.6f * mCircleRadius + mCircleRadius * 3.2f / 0.3f * mFraction,
                    mCenterX + mCircleRadius, mCenterY + 1.6f * mCircleRadius, mPaint);

            canvas.drawLine(mCenterX - mCircleRadius, mCenterY - 1.6f * mCircleRadius,
                    mCenterX - mCircleRadius, mCenterY + 1.6f * mCircleRadius, mPaint);

            if (mFraction != 0)
                canvas.drawArc(mRectF, 0f, 180f / 0.3f * mFraction, false, mPaint);

            canvas.drawArc(mBgRectF, -105 + 360 * mFraction, 360 * (1 - mFraction), false, mPaint);
        } else if (mFraction <= 0.6) {  //嗷~~ 下方曲线和三角形
            canvas.drawArc(mRectF, 180f / 0.3f * (mFraction - 0.3f), 180 - 180f / 0.3f * (mFraction - 0.3f), false, mPaint);

            mDstPath.reset();
            //mDstPath.lineTo(0 ,0);
            mPathMeasure.getSegment(0.02f * mPathLength, 0.38f * mPathLength + 0.42f * mPathLength / 0.3f * (mFraction - 0.3f),
                    mDstPath, true);
            canvas.drawPath(mDstPath, mPaint);

            canvas.drawArc(mBgRectF, -105 + 360 * mFraction, 360 * (1 - mFraction), false, mPaint);
        } else if (mFraction <= 0.8) {  //嗷~~ 三角形
            mDstPath.reset();
            //mDstPath.lineTo(0 ,0);
            mPathMeasure.getSegment(0.02f * mPathLength + 0.2f * mPathLength / 0.2f * (mFraction - 0.6f)
                    , 0.8f * mPathLength + 0.2f * mPathLength / 0.2f * (mFraction - 0.6f),
                    mDstPath, true);
            canvas.drawPath(mDstPath, mPaint);

            canvas.drawArc(mBgRectF, -105 + 360 * mFraction, 360 * (1 - mFraction), false, mPaint);
        } else {    //嗷~~ 弹性部分
            mDstPath.reset();
            //mDstPath.lineTo(0 ,0);
            mPathMeasure.getSegment(10 * mCircleRadius * (mFraction - 1)
                    , mPathLength,
                    mDstPath, true);
            canvas.drawPath(mDstPath, mPaint);
        }
    }

    public void play() {
        play(null);
    }

    private final ValueAnimator valueAnimator = ValueAnimator.ofFloat(1.f, 100.f);

    public void play(final Function0<Unit> endListener) {
        if (mCurrentState == STATE_PLAY) {
            return;
        }
        mCurrentState = STATE_PLAY;
        valueAnimator.cancel();
        valueAnimator.removeAllUpdateListeners();
        valueAnimator.setDuration(mDuration);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                mFraction = 1 - valueAnimator.getAnimatedFraction();
                if (endListener != null && mFraction == 0f) {
                    endListener.invoke();
                }
                invalidate();
            }
        });
        valueAnimator.start();
    }

    public void pause() {
        pause(null);
    }

    public void pause(final Function0<Unit> endListener) {
        if (mCurrentState == STATE_PAUSE) {
            return;
        }
        mCurrentState = STATE_PAUSE;
        valueAnimator.cancel();
        valueAnimator.removeAllUpdateListeners();
        valueAnimator.setDuration(mDuration);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                mFraction = valueAnimator.getAnimatedFraction();
                if (endListener != null && mFraction == 1f) {
                    endListener.invoke();
                }
                invalidate();
            }
        });
        valueAnimator.start();
    }

    public int getCurrentState() {
        return mCurrentState;
    }

    public void setDuration(int duration) {
        mDuration = duration;
    }

    private int dp2px(int dp) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
                getContext().getResources().getDisplayMetrics());
    }
}
